package com.yunhe.authority.service.company.impl;

import com.yunhe.authority.domain.authority.User;
import com.yunhe.authority.domain.company.Company;
import com.yunhe.authority.domain.company.Employee;
import com.yunhe.authority.option.UserProperties;
import com.yunhe.authority.repository.company.EmployeeRepository;
import com.yunhe.authority.repository.company.dao.EmployeeDao;
import com.yunhe.authority.service.company.CompanyService;
import com.yunhe.authority.service.company.EmployeeService;
import com.yunhe.common.constant.LogConsts;
import com.yunhe.common.constant.SystemConsts;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private LogUtil logUtil;

    @Autowired
    private UserProperties userProperties;

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private EmployeeDao employeeDao;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private RedisClient redisClient;

    private static final String MENU = "员工管理";
    private static final String SALT_M = "yunhe";
    private static final String SALT_V = "@yqlh";


    /**
     * 员工对象处理和判断
     *
     * @param employee 用户对象
     */
    private void processBeforeSave(Employee employee)
            throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException {
        //判断账号、用户密码、姓名是否为空
        if (StringUtil.isEmpty(employee.getPhone()) || StringUtil.isEmpty(employee.getTitle())) {
            throw new ArgumentErrorException("手机号、姓名不能为空");
        }

    }

    @Override
    public Employee findByPhone(String name) {
        return employeeRepository.findByPhone(name);
    }

    @Override
    public List<Employee> findListByPhone(String phone) {
        return employeeRepository.findListByPhone(phone);
    }

    @Override
    public void updateEmployeePasswordByPhone(String phone, String password) {
        employeeRepository.updatePasswordByPhone(phone, password);
    }

    private void bindEmployee(Long id, Long companyId, String roleIds) throws ArgumentErrorException, ObjectNotFoundException {
        String[] split = roleIds.split(",");
        if (split == null || split.length == 0) {
            throw new ArgumentErrorException("请关联对应的项目角色！");
        }

        //与企业进行绑定
        Company company = companyService.findById(companyId);
        if (company != null) {
            employeeRepository.bindCompany(id, companyId);
        }

        //与角色进行绑定
        List<Long> roleIdList = new ArrayList<>();
        for (String s : split) {
            roleIdList.add(Long.valueOf(s));
        }
        employeeRepository.bindCompanyRole(id, companyId, roleIdList);
    }

    /**
     * 新增员工
     * @param employee 员工对象
     * @param companyId 企业id
     * @param roleIds 角色组织id
     * @return
     * @throws ArgumentErrorException
     * @throws UniqueConstraintsException
     * @throws ObjectNotFoundException
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    @Override
    public Employee createEmployee(Employee employee, Long companyId, String roleIds) throws ArgumentErrorException, UniqueConstraintsException, ObjectNotFoundException {
        if (StringUtil.isEmpty(roleIds)) {
            throw new ArgumentErrorException("请关联员工的企业角色！");
        }

        employee.setId(null);
        employee.setCreateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date()));
        processBeforeSave(employee);

        //用户名统一为手机号
        employee.setName(employee.getPhone());
        //判断手机号是否已经被注册（同个公司下手机号唯一）
        Employee userByPhone = employeeRepository.findByPhoneAndId(employee.getName(), companyId);
        if (userByPhone != null) {
            if (employee.getId() == null || userByPhone.getId().longValue() != employee.getId().longValue()) {
                throw new UniqueConstraintsException("该手机号已有账户");
            }
        }

        Employee byPhone = employeeRepository.findByPhone(employee.getPhone());
        if (byPhone != null) {
            //统一密码
            employee.setPassword(byPhone.getPassword());
        }

        //新账号默认密码设置
        if (employee.getId() == null) {
            employee.setPassword(MD5Util.encode(MD5Util.encode(userProperties.getRootDefaultPassword(), SALT_V), SALT_M));
            employee.setActivity("1");
        }

        Employee newEmployee = employeeRepository.save(employee);
        bindEmployee(newEmployee.getId(), companyId, roleIds);
        return newEmployee;
    }

    /**
     * 根据ids删除用户
     * @param employeeIds
     * @throws ArgumentErrorException
     */
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    @Override
    public void deleteEmployee(String employeeIds) throws ArgumentErrorException {
        if (StringUtil.isEmpty(employeeIds)) {
            throw new ArgumentErrorException("请选择要删除的账号信息");
        }
        String[] split = employeeIds.split(",");
        if (split.length <= 0) {
            throw new ArgumentErrorException("请选择要删除的账号信息");
        }
        List<Long> ids = new ArrayList<>();
        for (String s : split) {
            ids.add(Long.valueOf(s));
        }
        //解除员工与企业、角色之间的关系
        employeeRepository.unbindAllCompanies(ids);
        employeeRepository.unbindAllRoles(ids);
        //删除用户
        employeeRepository.deleteByIds(ids);
        logUtil.createLog(LogConsts.LOG_TYPE_CODE.ACTION, MENU, SystemConsts.ACTION.DELETE);
    }

    /**
     * 批量重置员工密码
     * @param ids
     * @return
     * @throws ArgumentErrorException
     */
    @Override
    public List<Employee> resetPassword(String ids) throws ArgumentErrorException {
        if(StringUtil.isEmpty(ids)){
            throw new ArgumentErrorException("请选择用户进行操作！");
        }
        String[] split = ids.split(",");
        List<Employee> result = new ArrayList<>();
        for (String id : split) {
            Employee employee = employeeRepository.updatePassword(Long.valueOf(id), MD5Util.encode(MD5Util.encode(userProperties.getDefaultPassword(), SALT_V), SALT_M));
            //发短信
            if (employee != null && employee.getPhone() != null) {
                String phone = employee.getPhone();
                //这边去更新所有这个手机号的密码，都重置为默认的
                employeeRepository.updateAllSamePhoneEmployeePassword(phone, MD5Util.encode(MD5Util.encode(userProperties.getDefaultPassword(), SALT_V), SALT_M));

                String password = userProperties.getRootDefaultPassword();
                Map<String, String> map = new HashMap<>();
                map.put("code", password);
                String templateCode = "SMS_218727647";
                String templateParam = "{\"code\":\"" + password + "\"}";
                try {
                    SmsUtil.sendSms(phone, map, templateCode, templateParam);
                } catch (Exception e) {
                    throw new ArgumentErrorException("短信发送失败！");
                }
                result.add(employee);
                //用户校验重置密码后用户第一次登录提示修改密码
                redisClient.set(employee.getId()+"-resetPassword","success");
            }
        }

        return result;
    }

    /**
     * 禁用/恢复员工账号
     * @param ids
     * @param activity
     * @param headerUser
     * @throws ArgumentErrorException
     */
    @Override
    public void disableRecoveryEmployee(String ids, String activity, User headerUser) throws ArgumentErrorException {
        if (StringUtil.isEmpty(ids)) {
            throw new ArgumentErrorException("请选择员工进行操作！");
        }
        String[] split = ids.split(",");
        if (split.length <= 0) {
            throw new ArgumentErrorException("请选择员工进行操作！");
        }
        List<Long> employeeIds = new ArrayList<>();
        for (String s : split) {
            employeeIds.add(Long.valueOf(s));
        }
        String remark = null;
        String nowTime = DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date());
        if (headerUser != null) {
            if ("1".equals(activity)) {
                remark = headerUser.getTitle() + nowTime + "恢复";
            } else {
                remark = headerUser.getTitle() + nowTime + "禁用";
            }
        }

        employeeRepository.updateActivity(employeeIds, activity, remark, nowTime);
    }

    /**
     * 根据ID获得员工对象
     * @param employeeId 员工ID
     * @return
     */
    @Override
    public Employee findByEmployeeId(Long employeeId) {
        return employeeRepository.findById(employeeId).orElse(null);
    }

    /**
     * 修改员工对象
     * @param employee
     * @param companyId
     * @param roleIdList
     * @return
     * @throws ObjectNotFoundException
     * @throws ArgumentErrorException
     * @throws UniqueConstraintsException
     */
    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void updateEmployee(Employee employee, Long companyId, List<Long> roleIdList) throws ObjectNotFoundException, ArgumentErrorException, UniqueConstraintsException {
        Employee oldEmployee = this.findByEmployeeId(employee.getId());
        if (oldEmployee == null) {
            throw new ObjectNotFoundException("找不到ID为" + employee.getId() + "的用户");
        }

        if (roleIdList.size() <= 0) {
            throw new ArgumentErrorException("请选择员工的角色！");
        }

        Optional.ofNullable(employee.getPhone()).ifPresent(oldEmployee::setPhone);
        Optional.ofNullable(employee.getTitle()).ifPresent(oldEmployee::setTitle);
        Optional.ofNullable(employee.getSex()).ifPresent(oldEmployee::setSex);
        Optional.ofNullable(employee.getActivity()).ifPresent(oldEmployee::setActivity);
        Optional.ofNullable(employee.getMail()).ifPresent(oldEmployee::setMail);

        processBeforeSave(employee);
        employeeRepository.unbindAllRoles(Arrays.asList(employee.getId()));
        employeeRepository.bindCompanyRole(employee.getId(), companyId, roleIdList);
        employeeRepository.save(oldEmployee);
    }

    @Override
    public Iterable<Employee> getEmployeeByCondition(Long companyId, String roleType, PageParam pageParam) throws ArgumentErrorException {
        Iterable<Employee> employees = null;
        if (companyId == null) {
            throw new ArgumentErrorException("请选择企业进行相关员工查询！");
        }
        if (QueryUtil.needPaging(pageParam)) {
            employees = employeeDao.getEmployeeByCondition(companyId, roleType, pageParam);
        }

        return employees;
    }

    @Override
    public Page<Employee> getEmployeesByCompanyIdAndRoleId(Long companyId, Long roleId, String keywords, PageParam pageParam) {
        Page<Employee> employees = employeeDao.getEmployeesByCompanyIdAndRoleId(companyId, roleId, keywords, pageParam);
        return employees;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void employeeUnbindCompanyRole(Long employeeId, Long roleId) {
        employeeRepository.employeeUnbindCompanyRole(employeeId, roleId);
    }

    @Override
    public List<Employee> getEmployeesByPhoneAndPassword(String phone, String password) {
        return employeeRepository.getEmployeesByPhoneAndPassword(phone, password);
    }

}
